Skip to content

Axum / Actix Web 工程实践深化

1. 这是什么

当你已经会写基础路由、handler、提取器和状态管理后,下一步就不再是“框架能不能跑起来”,而是:

  • 项目怎么分层
  • handler 要薄到什么程度
  • 状态、配置、数据库、错误处理如何组织
  • 路由、中间件、服务层、仓储层如何协作
  • 项目怎样从 demo 走向可维护工程

这篇讨论的不是某一个 API 小技巧,
而是 Axum / Actix Web 在进入真实项目后常见的工程化问题。

一句话理解:

  • 入门阶段关注“接口怎么写”
  • 深化阶段关注“项目怎么长久维护”

2. 为什么这个主题很重要

因为 Web 框架最容易让人快速产生成就感:

  • 几个路由很快能跑起来
  • handler 很快能返回 JSON
  • 数据库一接上,好像项目就成型了

但真实问题通常会在之后出现:

  • handler 里堆满业务逻辑
  • 配置、状态、数据库连接四处传递
  • 错误处理风格不统一
  • 测试很难写
  • 中间件越叠越多却没人说得清顺序
  • 路由和业务耦合得越来越死

所以工程实践深化讲的不是“再多一个接口”,
而是:

  • 如何让 Web 项目在复杂度上升后仍然保持清晰

3. 先建立直觉

3.1 框架只是边界层,不应该吞掉整个应用

很多初学者一旦开始写 Web 项目,就容易让整个项目都围着框架转:

  • handler 直接写业务逻辑
  • handler 直接操作数据库
  • handler 直接拼错误响应
  • handler 里同时做鉴权、校验、事务和日志

短期看很快,长期看会非常难维护。
更成熟的直觉应该是:

  • Axum / Actix 是应用的 HTTP 边界层,不是整个业务模型本身

也就是说:

  • Web 框架负责承接请求与响应
  • 业务规则应该尽量沉到更稳定的服务边界中
  • 数据访问应该进一步沉到底层数据边界中

3.2 工程实践的核心不是层数多,而是边界清楚

很多人一讲工程化,就立刻想到:

  • controller / service / repository / dto / vo / manager / facade

但真正重要的并不是层名,而是:

  • 哪一层负责输入输出边界
  • 哪一层负责业务规则
  • 哪一层负责数据访问
  • 哪一层负责横切能力

如果边界没定义清楚,层再多也只是复杂度伪装。

4. Axum / Actix 深化时首先要解决的问题

4.1 保持 handler 薄

一个健康的 Web 项目里,handler 通常应该更像:

  • 接参数
  • 调服务
  • 组响应
  • 处理边界层错误映射

而不应该承担:

  • 大段业务规则
  • 复杂数据库查询编排
  • 大量事务细节
  • 各种横切逻辑

为什么?因为 handler 天然与框架绑定更紧。
如果业务逻辑也一起绑进去,测试、复用和演化成本都会迅速上升。

4.2 状态管理要尽早统一

进入工程实践后,你很快会遇到各种共享状态:

  • 配置
  • 数据库连接池
  • 缓存客户端
  • 外部服务客户端
  • tracing / metrics 相关上下文

如果没有统一的应用状态组织方式,就容易出现:

  • 到处 clone
  • 到处传散乱依赖
  • 模块之间边界越来越模糊

所以实践深化里很重要的一件事是:

  • 尽早定义应用状态的组织方式和注入方式

4.3 错误处理、中间件、日志要形成统一边界

一个工程项目里,不能每个 handler 各玩各的:

  • 有的返回字符串
  • 有的直接返回状态码
  • 有的打日志
  • 有的吞错误

这会让维护和排障非常痛苦。
所以随着项目成长,需要逐步建立:

  • 统一错误响应语义
  • 统一日志和 tracing 入口
  • 统一 request id / user context 注入
  • 统一中间件职责与顺序

5. Axum 和 Actix 在工程化层面的共同点

虽然两者 API 风格不同,但在工程化问题上,关心的核心其实差不多:

  • 路由如何组织
  • 模块边界如何划分
  • 状态如何注入
  • 错误如何收敛
  • 中间件如何布置
  • 测试如何进行
  • 数据访问与业务逻辑如何分层

这说明你真正要学的不是“某个框架独有魔法”,
而是 Web 服务的普遍工程规律。

6. Axum / Actix 深化时最值得建立的几个能力

6.1 从“按接口写代码”转向“按领域组织模块”

如果项目一开始只是少量接口,按文件随手加路由问题不大。
但接口一多,就更适合围绕领域或业务边界组织模块,而不是把所有 handler 堆在一起。

这会带来几个好处:

  • 路由与业务边界更一致
  • 团队协作时更容易定位代码
  • 模块扩展时不容易形成巨型文件

6.2 把业务编排从 HTTP 细节里抽出来

HTTP 参数提取、header、状态码这些都属于边界层细节。
真正稳定的业务规则,最好不要与这些细节紧耦合。

这样做的好处是:

  • 测试更简单
  • 更容易在 CLI、任务系统、RPC 等其他入口复用业务逻辑
  • 框架切换成本更低

6.3 让数据访问边界单独成型

数据库访问如果直接写死在 handler 里,后面很容易失控。
工程深化的一个关键点是:

  • 让查询、事务、数据持久化边界成为独立可理解的一层

不是为了层数好看,
而是为了把“HTTP 处理”和“数据持久化”这两个变化原因分开。

6.4 为测试和演化留空间

一个真正工程化的 Web 项目,必须能回答:

  • 业务规则是否能脱离 HTTP 测试
  • handler 是否能做集成测试
  • 数据访问层是否能被替换或隔离
  • 配置与外部依赖是否容易注入测试环境

如果这些都做不到,项目规模一上去就会开始脆弱。

7. 常见误区

7.1 误区一:框架用得熟,就等于工程实践成熟

不对。
熟悉 API 只是入门,真正难的是结构设计和复杂度控制。

7.2 误区二:项目分很多层就一定更专业

不对。
边界不清楚时,多层只会增加跳转成本和理解负担。

7.3 误区三:先把功能堆出来,后面再重构也来得及

很多时候来不及。
Web 项目一旦接口增多、依赖增多、调用链增长,重构成本会上升得很快。

7.4 误区四:Axum 和 Actix 不同,所以工程实践方法也完全不同

并不是。
两者在框架细节上有差异,但工程化关注点高度相似。

8. 一个更实用的判断思路

如果你在看一个 Axum / Actix 项目是否进入了更成熟的工程状态,可以先问:

  1. handler 是否足够薄,还是已经堆满业务逻辑
  2. 配置、状态、数据库客户端是否有统一组织方式
  3. 错误处理和中间件是否统一,而不是散落在各处
  4. 业务规则是否能脱离 HTTP 边界独立测试
  5. 数据访问边界是否清晰,还是直接耦合在路由代码里

9. 建议学习顺序

建议按这个顺序深化:

  1. 先把 handler、service、repository 的边界感建立起来
  2. 再统一应用状态与配置注入方式
  3. 再统一错误处理、日志、tracing 与中间件链路
  4. 再改进路由组织与模块划分
  5. 最后围绕测试、部署、可观测性和容量治理继续深化

10. 自测标准

  • 能解释为什么 Web 框架只是应用边界层,而不是业务本体
  • 能理解 handler 薄、业务边界清晰对维护性的重要性
  • 能意识到配置、状态、错误处理和中间件需要统一组织
  • 能判断一个项目是“接口能跑”还是“结构可维护”
  • 能知道 Axum / Actix 的工程深化重点更多是架构与边界,而不是 API 技巧